﻿#pragma once
namespace LK
{
	struct ICloneables :virtual Object
	{
		typedef PCloneables PObj;
		typedef ICloneables IObj;
		/*动态获取类型信息*/
		virtual PType GetType()const;
		/*operator&重载*/
		IObj*operator&() { if (RefCount<0)++RefCount; return this; }
		IObj const*operator&()const { if (RefCount<0)++RefCount; return this; }
		virtual void SwapWith(Object&) { Throw<PNotSupportException>(); }
		/**@brief 获取该对象的浅表副本*/
		virtual ICloneables* Clone()const = 0;
	};
	struct PCloneables :PObject
	{
		typedef PCloneables PObj; 
		typedef ICloneables IObj; 
		/**@brief 默认构造函数*/
		PCloneables() {}
		/**@brief 复制构造函数*/
		inline PCloneables(PCloneables const&t) { PObject::SetTo(t.PObject::GetPtr()); }
		/**@brief 从对象指针构造*/
		inline PCloneables(ICloneables const* p) { PObject::SetTo(StaticCastPointer(p)); }
		/**@brief 赋值*/
		inline PCloneables& operator=(PCloneables const&r) { PObject::SetTo(r.PObject::GetPtr()); return *this; }
		/**@brief 获取对象指针，并在对象指针为空时抛出异常*/
		inline ICloneables* Ptr()const { return CheckPointer<ICloneables>(PObject::GetPtr()); }
		/**@brief 获取对象指针*/
		inline ICloneables* GetPtr()const { return CastPointer<ICloneables>(PObject::GetPtr()); }
		/**@brief 重载operator->*/
		inline ICloneables* operator->()const { return Ptr(); }
		/**@brief 检查对象引用计数如果不为1，则进行Clone。空引用将抛出异常*/
		inline ICloneables* OnePtr() { if (RefCount != 1) { PObject::SetTo(((PCloneables*)this)->Ptr()->Clone()); } return CastPointer<ICloneables>(PObject::GetPtr()); }
		/**@brief 获取对象类型*/
		inline PType GetType()const;
		/**@brief 制作浅表副本*/
		PCloneables Clone()const { return Ptr()->Clone(); }
		/**@brief 添加类型信息*/
		static void AddTypeInfo();
	};
}